#include "login_authority_task.h"
#include "../MessageProcess.h"
#include <uam/UserAccountManager.h>
#include <core/sharedata/login_data.h>
#include <core/Utility.h>
#include <qbprotocol/include/SSQBModel.h>
#include <qbkernel/include/qb_base.h>
#include <bondlib/BondContainer.h>
#include <qbtools/message/MessagePoster.h>
#include <thread>

namespace qb
{
	typedef void (CLoginAuthorityTask::*authorityFunc)(void);
	struct AuthorityTask
	{
		_eFunID_t			funid;
		authorityFunc		func;
	};

	AuthorityTask authorityTasks[] = 
	{ 
		{E_FID_QB_USER_PERMISSION_REQ,	&CLoginAuthorityTask::RequestUserPermission},
		{E_FID_QB_CDC_AUTHORITY_REQ_V2, &CLoginAuthorityTask::RequestCDCAuthority}, 
		{E_FID_QB_CSI_AUTHORITY_REQ,	&CLoginAuthorityTask::RequestCSIAuthority}, 
	};

    CLoginAuthorityTask::CLoginAuthorityTask()
    {
		for (uint32_t i = 0; i < sizeof(authorityTasks) / sizeof(AuthorityTask); i++)
		{
			qbBase::getMessageBond()->RegisterMsgProcessor(authorityTasks[i].funid, this);
		}
		m_ptr.reset(this);
    }

    CLoginAuthorityTask::~CLoginAuthorityTask()
    {
		for (uint32_t i = 0; i < sizeof(authorityTasks) / sizeof(AuthorityTask); i++)
		{
			qbBase::getMessageBond()->UnRegisterMsgProcessor(authorityTasks[i].funid, this);
		}
    }

	void CLoginAuthorityTask::StartImpl()
	{
		SSUserAccountManager::instance().SetCDCAutority(NULL);
		SSUserAccountManager::instance().init();
		CBondContainer::instance().ClearCDCDataAll();
		loginData::instance().SetCurrentStatus(eNetStatus_Authority);

		m_setAuthority.clear();
		for (uint32_t i = 0; i < sizeof(authorityTasks) / sizeof(AuthorityTask); i++)
		{
			m_setAuthority.insert(authorityTasks[i].funid);
			(this->*authorityTasks[i].func)();
		}
		SSUserAccountManager::instance().requestSystime();
		SSUserAccountManager::instance().requestBroker();
		SSUserAccountManager::instance().requestQbFlags();
		SSUserAccountManager::instance().requestGlobalSwitch();
		SSUserAccountManager::instance().requestUserInfo();
	}

	void CLoginAuthorityTask::TerminateImpl()
	{

	}

	void CLoginAuthorityTask::RequestUserPermission()
	{
		SSRequestMsg Req;
		memset(&Req, 0, sizeof(SSRequestMsg));
		Req.m_MsgType = SSReqType_Message;
		Req.m_FuncID = E_FID_QB_USER_PERMISSION_REQ;

		QBAuthorityQueryReq_t req;
		QBAuthorityQueryReq_t* ptr = &req;
		memset(ptr, 0, sizeof(QBAuthorityQueryReq_t));
		strcpy(ptr->m_UserId, loginData::instance().UserInfo().strUserID.c_str());
		strcpy(ptr->m_CompanyId, loginData::instance().UserInfo().strCompanyId.c_str());
		Req.m_pRequest = (void*)ptr;

		MessagePoster poster(loginData::instance().ConnectID(), &Req, [](qb::proto::Message& msg, qb::SSRequestMsg*) {
			qb::proto::VariantMap submsg;
			submsg.setString("UserId", loginData::instance().UserInfo().strUserID);
			submsg.setString("CompanyId", loginData::instance().UserInfo().strCompanyId);
			msg.SetMap("xQBAuthorityQueryReq", submsg);
			});
		if (poster.send() < 0)
		{
			NotifyFailed(eNetStatus_Authority, eNetError_SendToServerFailed);
		}
	}

	void CLoginAuthorityTask::RequestCDCAuthority()
	{
		SSRequestMsg Req;
		memset(&Req, 0, sizeof(SSRequestMsg));
		Req.m_MsgType = SSReqType_Message;
		Req.m_FuncID = E_FID_QB_CDC_AUTHORITY_REQ;

		xCDCAuthorityReq_c req;
		FIELDCOPY(req.m_UserId, loginData::instance().UserInfo().strUserID.c_str());
		FIELDCOPY(req.m_CompanyId, loginData::instance().UserInfo().strCompanyId.c_str());
		Req.m_pRequest = (void*)&req;

		MessagePoster poster(loginData::instance().ConnectID(), &Req, nullptr);
		if (poster.send() < 0)
		{
			NotifyFailed(eNetStatus_Authority, eNetError_SendToServerFailed);
		}

		Req.m_RequestID = 0;
		Req.m_FuncID = E_FID_QB_CDC_AUTHORITY_REQ_V2;
		MessagePoster poster2(loginData::instance().ConnectID(), &Req, nullptr);
		if (poster2.send() < 0)
		{
			NotifyFailed(eNetStatus_Authority, eNetError_SendToServerFailed);
		}
	}

	void CLoginAuthorityTask::RequestCSIAuthority()
	{
		SSRequestMsg Req;
		memset(&Req, 0, sizeof(SSRequestMsg));
		Req.m_MsgType = SSReqType_Message;
		Req.m_FuncID = E_FID_QB_CSI_AUTHORITY_REQ;

		xCSIAuthorityReq_c req;
		Req.m_pRequest = (void*)&req;

		MessagePoster poster(loginData::instance().ConnectID(), &Req, [](qb::proto::Message& msg, qb::SSRequestMsg*) {
			qb::proto::VariantMap submsg;
			submsg.setString("UserId", loginData::instance().UserInfo().strUserID);
			submsg.setString("CompanyId", loginData::instance().UserInfo().strCompanyId);
			msg.SetMap("xCSIAuthorityReq", submsg);
			});
		if (poster.send() < 0)
		{
			NotifyFailed(eNetStatus_Authority, eNetError_SendToServerFailed);
		}
	}

	void CLoginAuthorityTask::OnTimeout()
	{
		//用户权限是必须的，其他可以暂时收不到
		auto iter = m_setAuthority.find(E_FID_QB_USER_PERMISSION_REQ);
		if (iter != m_setAuthority.end())
			return CTask::OnTimeout();

		NotifyLoginStep(eNetStatus_Authority, 0);
		NotifyFinished();
	}

	void CLoginAuthorityTask::AuthorityTaskFinish(_eFunID_t funcid)
	{
		std::set<_eFunID_t>::iterator it = m_setAuthority.find(funcid);
		if (it != m_setAuthority.end())
		{
			m_setAuthority.erase(it);
		}

		if (0 == m_setAuthority.size())
		{
			NotifyLoginStep(eNetStatus_Authority, 0);
			NotifyFinished();
		}
	}

	STDMETHODIMP_(void) CLoginAuthorityTask::OnResponse(THIS_ int32_t funcId, const SSAckMsg& msg)
	{
		if (!msg.m_pRet)
		{
			if(funcId == E_FID_QB_USER_PERMISSION_REQ)
				NotifyFailed(eNetStatus_Authority, eNetError_DataParseError);
			return;
		}

		if (E_FID_QB_USER_PERMISSION_REQ == funcId)
		{
			xQBUserPermissionAck_c* pdata = (xQBUserPermissionAck_c*)msg.m_pRet;
			SSUserAccountManager& uam = SSUserAccountManager::instance();
			if (strcmp(uam.GetUserInfo().m_UserId, pdata->m_UserId) != 0 || strcmp(uam.GetUserInfo().m_CompanyId, pdata->m_CompanyId) != 0)
			{
				NotifyFailed(eNetStatus_Authority, eNetError_DataParseError);
				return;
			}

			if(msg.m_IsReceving == 0)
				AuthorityTaskFinish((_eFunID_t)funcId);
		}
		else if (E_FID_QB_CDC_AUTHORITY_REQ_V2 == funcId)
		{
			AuthorityTaskFinish((_eFunID_t)funcId);
		}
		else if (E_FID_QB_CSI_AUTHORITY_REQ == funcId)
		{
			AuthorityTaskFinish((_eFunID_t)funcId);
		}
	}
}
